/**
 * \file
 *
 * \brief AUTOSAR FiM
 *
 * This file contains the implementation of the AUTOSAR
 * module FiM.
 *
 * \author Elektrobit Automotive GmbH, 91058 Erlangen, Germany
 *
 * Copyright 2005 - 2013 Elektrobit Automotive GmbH
 * All rights exclusively reserved for Elektrobit Automotive GmbH,
 * unless expressly agreed to otherwise.
 */


/*==================[inclusions]============================================*/
/* !LINKSTO dsn.FiM.IncludeStr,1 */

#include <Std_Types.h>         /* AUTOSAR standard types */
#include <TSAutosar.h>         /* EB specific standard types */
#include <TSMem.h>             /* TS_MemSet() */

#include <FiM.h>               /* Module public API */
#include <FiM_Int.h>           /* Module internal interface */
#include <FiM_Trace.h>         /* Dbg related macros for FiM */
#include <SchM_FiM.h>          /* Header of Schedule Manager for FiM */

#if (FIM_DEV_ERROR_DETECT == STD_ON)
# include <Det.h>              /* Det API */
#endif

#include <Dem.h>               /* The APIs to report errors as well as the required
                                * EventId symbols are included. */

#if (FIM_INCLUDE_RTE == STD_ON)
# include <Rte_FiM.h>          /* API generated by RTE */
#endif

/*==================[macros]================================================*/
/* !LINKSTO FIM.Version.Check,1 */

/*------------------[AUTOSAR vendor identification check]-------------------*/

#if (!defined FIM_VENDOR_ID) /* configuration check */
#error FIM_VENDOR_ID must be defined
#endif

#if (FIM_VENDOR_ID != 1U) /* vendor check */
#error FIM_VENDOR_ID has wrong vendor id
#endif

/*------------------[AUTOSAR release version identification check]----------*/

#if (!defined FIM_AR_RELEASE_MAJOR_VERSION) /* configuration check */
#error FIM_AR_RELEASE_MAJOR_VERSION must be defined
#endif

/* major version check */
#if (FIM_AR_RELEASE_MAJOR_VERSION != 4U)
#error FIM_AR_RELEASE_MAJOR_VERSION wrong (!= 4U)
#endif

#if (!defined FIM_AR_RELEASE_MINOR_VERSION) /* configuration check */
#error FIM_AR_RELEASE_MINOR_VERSION must be defined
#endif

/* minor version check */
#if (FIM_AR_RELEASE_MINOR_VERSION != 0U )
#error FIM_AR_RELEASE_MINOR_VERSION wrong (!= 0U)
#endif

#if (!defined FIM_AR_RELEASE_REVISION_VERSION) /* configuration check */
#error FIM_AR_RELEASE_REVISION_VERSION must be defined
#endif

/* revision version check */
#if (FIM_AR_RELEASE_REVISION_VERSION != 3U )
#error FIM_AR_RELEASE_REVISION_VERSION wrong (!= 3U)
#endif

/*------------------[AUTOSAR module version identification check]-----------*/

#if (!defined FIM_SW_MAJOR_VERSION) /* configuration check */
#error FIM_SW_MAJOR_VERSION must be defined
#endif

/* major version check */
#if (FIM_SW_MAJOR_VERSION != 2U)
#error FIM_SW_MAJOR_VERSION wrong (!= 2U)
#endif

#if (!defined FIM_SW_MINOR_VERSION) /* configuration check */
#error FIM_SW_MINOR_VERSION must be defined
#endif

/* minor version check */
#if (FIM_SW_MINOR_VERSION < 1U)
#error FIM_SW_MINOR_VERSION wrong (< 1U)
#endif

#if (!defined FIM_SW_PATCH_VERSION) /* configuration check */
#error FIM_SW_PATCH_VERSION must be defined
#endif

/* patch version check */
#if (FIM_SW_PATCH_VERSION < 8U)
#error FIM_SW_PATCH_VERSION wrong (< 8U)
#endif

/*------------------[inhibition masks]--------------------------------------*/
/* !LINKSTO FIM.FidStatus.BitDefinition,1 */

#if (defined FIM_LAST_FAILED_MASK)
#error FIM_LAST_FAILED_MASK already defined
#endif
/** \brief Last Failed requires testing bit 0 of extended event status */
#define FIM_LAST_FAILED_MASK            0x01U

#if (defined FIM_NOT_TESTED_MASK)
#error FIM_NOT_TESTED_MASK already defined
#endif
/** \brief Not Tested requires testing bit 6 of extended event status */
#define FIM_NOT_TESTED_MASK             0x40U

#if (defined FIM_TESTED_MASK)
#error FIM_TESTED_MASK already defined
#endif
/** \brief Tested requires testing bit 6 of extended event status */
#define FIM_TESTED_MASK                 0x40U

#if (defined FIM_TESTED_AND_FAILED_MASK)
#error FIM_TESTED_AND_FAILED_MASK already defined
#endif
/** \brief Tested and Failed requires testing bit 6 and bit 0 of extended
 ** event status */
#define FIM_TESTED_AND_FAILED_MASK      0x41U

#if (defined FIM_LAST_FAILED_RESULT)
#error FIM_LAST_FAILED_RESULT already defined
#endif
/** \brief Bit 0 of extended event status will be set for Last Failed */
#define FIM_LAST_FAILED_RESULT          0x01U

#if (defined FIM_NOT_TESTED_RESULT)
#error FIM_NOT_TESTED_RESULT already defined
#endif
/** \brief Bit 6 of extended event status will be set for Not Tested */
#define FIM_NOT_TESTED_RESULT           0x40U

#if (defined FIM_TESTED_RESULT)
#error FIM_TESTED_RESULT already defined
#endif
/** \brief Bit 6 of extended event status will be reset for Tested */
#define FIM_TESTED_RESULT               0x00U

#if (defined FIM_TESTED_AND_FAILED_RESULT)
#error FIM_TESTED_AND_FAILED_RESULT already defined
#endif
/** \brief Bit 6 of extended event status will be reset for Tested
 ** and Bit 0 will be set for Failed */
#define FIM_TESTED_AND_FAILED_RESULT    0x01U

#if (defined FIM_MASK_COUNT)
#error FIM_MASK_COUNT already defined
#endif
/** \brief Count of inhibition masks */
#define FIM_MASK_COUNT                  4U

/*------------------[helper macros]-----------------------------------------*/

#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_OFF)

/** \brief Get inhibition mask from ::FiM_EventCfgType
 *
 * The inhibition mask of an assigned event is encoded in the upper 2 bits. */
#define FIM_EVENT_CFG_INH_MASK_IDX(a, i) ((uint8)((a)[(i)] >> 14U))

/** \brief Get Dem Event Id from ::FiM_EventCfgType */
#define FIM_EVENT_CFG_EVENT_ID(a, i)     \
  ((Dem_EventIdType)((a)[(i)] & 0x3FFFU))

/** \brief Get inhibition mask from EventCfg by FID and array-index */
#define FIM_INH_MASK_IDX(fid, i)         \
  FIM_EVENT_CFG_INH_MASK_IDX(FiM_FidConfig[(fid)].EventCfg, (i))

/** \brief Get Dem Event Id from EventCfg by FID and array-index */
#define FIM_EVENT_ID(fid, i)             \
  FIM_EVENT_CFG_EVENT_ID(FiM_FidConfig[(fid)].EventCfg, (i))

#else /* FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON */

/** \brief Get inhibition mask from ::FiM_FidCfgType
 *
 * The inhibition mask of an assigned FID is encoded in the upper 2 bits. */
#define FIM_FID_CFG_INH_MASK_IDX(a, i) ((uint8)((a)[(i)] >> 14U))

/** \brief Get FID from ::FiM_FidCfgType */
#define FIM_FID_CFG_FID(a, i)            \
  ((FiM_FunctionIdType)((a)[(i)] & 0x3FFFU))

/** \brief Get inhibition mask from FidCfg by event-index and array-index */
#define FIM_INH_MASK_IDX(evtIdx, i)      \
  FIM_FID_CFG_INH_MASK_IDX(FiM_EvtConfig[(evtIdx)].FidCfg, (i))

/** \brief Get FID from FidCfg by event-index and array-index */
#define FIM_FID(evtIdx, i)               \
  FIM_FID_CFG_FID(FiM_EvtConfig[(evtIdx)].FidCfg, (i))

/** \brief Symbolic name of invalid event ID (derived from Dem SWS) */
#define FIM_EVENT_ID_INVALID  0U

/** \brief To get the mid value for binary search */
#define GET_MID_VALUE(high, low) (((low) + (high)) / 2)

#endif /* FIM_EVENT_UPDATE_TRIGGERED_BY_DEM */

#if (FIM_DEV_ERROR_DETECT == STD_ON)
/** \brief Report FiM development error */
#define FIM_DET_REPORT_ERROR(ApiId, ErrorId) \
  ((void)Det_ReportError(FIM_MODULE_ID, FIM_INSTANCE_ID, (ApiId), (ErrorId)))
#endif

/* !LINKSTO dsn.FiM.SchMEnterCS,1 */
/** \brief Macro to enter the generic critcal section */
#define FIM_ENTER_EXCLUSIVE_AREA SchM_Enter_FiM_SCHM_FIM_EXCLUSIVE_AREA_0

/* !LINKSTO dsn.FiM.SchMLeaveCS,1 */
/** \brief Macro to leave the generic FiM critcal section */
#define FIM_EXIT_EXCLUSIVE_AREA SchM_Exit_FiM_SCHM_FIM_EXCLUSIVE_AREA_0


/*==================[type definitions]======================================*/

/*==================[external function declarations]========================*/

/*==================[internal function declarations]========================*/

#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON)

#define FIM_START_SEC_CODE
#include <MemMap.h>

/** \brief Determines inhibition status of all FIDs */
STATIC FUNC(void, FIM_CODE) FiM_DetermineInhibition(void);

/** \brief Gets the event-index of the tested and failed inhibion events.
 **
 ** This function gets the index of the event from the global array
 ** which contains only specific FIDs mapped to the event.
 **
 ** \param[in] EventId  Identification of an Event
 ** \param[out] EvtIdx  Index of Event Id
 **
 ** \return Result of the searching
 ** \retval E_OK     EvtIdx was found
 ** \retval E_NOT_OK no EvtIdx exists
 */
STATIC FUNC(Std_ReturnType, FIM_CODE) FiM_EventSearch
(
  Dem_EventIdType                         EventId,
  P2VAR(uint16, AUTOMATIC, FIM_APPL_DATA) EvtIdx
);

#define FIM_STOP_SEC_CODE
#include <MemMap.h>

#endif /* (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON) */

/*==================[external constants]====================================*/

/*==================[internal constants]====================================*/

#define FIM_START_SEC_CONST_UNSPECIFIED
#include <MemMap.h>

/** \brief Array of inhibition masks */
STATIC CONST(Dem_EventStatusExtendedType, FIM_CONST)
  FiM_InhMask[FIM_MASK_COUNT] =
{
  FIM_LAST_FAILED_MASK,
  FIM_NOT_TESTED_MASK,
  FIM_TESTED_MASK,
  FIM_TESTED_AND_FAILED_MASK
};

/** \brief Array of expected result after masking */
STATIC CONST(Dem_EventStatusExtendedType, FIM_CONST)
  FiM_InhResult[FIM_MASK_COUNT] =
{
  FIM_LAST_FAILED_RESULT,
  FIM_NOT_TESTED_RESULT,
  FIM_TESTED_RESULT,
  FIM_TESTED_AND_FAILED_RESULT
};

#define FIM_STOP_SEC_CONST_UNSPECIFIED
#include <MemMap.h>

/*==================[external data]=========================================*/

/*==================[internal data]=========================================*/

#if (FIM_DEV_ERROR_DETECT == STD_ON)

#define FIM_START_SEC_VAR_INIT_8
#include <MemMap.h>

/** \brief Initialisation status of the FiM module
 *
 * Only used in DET checks */
STATIC VAR(boolean, FIM_VAR) FiM_Initialized = FALSE;

#define FIM_STOP_SEC_VAR_INIT_8
#include <MemMap.h>

#endif

#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON)

#define FIM_START_SEC_VAR_NO_INIT_8
#include <MemMap.h>

/* !LINKSTO FIM065_Implicit2,1 */
/** \brief Inhibition counter of FiM FIDs */
STATIC VAR(uint8, FIM_VAR) FiM_FidInhibitCounter[FIM_FID_NUM];

#define FIM_STOP_SEC_VAR_NO_INIT_8
#include <MemMap.h>

#endif

/*==================[external function definitions]=========================*/

#define FIM_START_SEC_CODE
#include <MemMap.h>

/*------------------[FiM_GetVersionInfo]------------------------------------*/
#if (FIM_VERSION_INFO_API == STD_ON)
FUNC(void, FIM_CODE) FiM_GetVersionInfo
(
  P2VAR(Std_VersionInfoType, AUTOMATIC, FIM_APPL_DATA) VersionInfoPtr
)
{
  DBG_FIM_GETVERSIONINFO_ENTRY(VersionInfoPtr);

#if (FIM_DEV_ERROR_DETECT == STD_ON)
  if (NULL_PTR == VersionInfoPtr)
  {
    FIM_DET_REPORT_ERROR(FIM_SID_GET_VERSION_INFO, FIM_E_INVALID_POINTER);
  }
  else
#endif
  {
    VersionInfoPtr->vendorID         = FIM_VENDOR_ID;
    VersionInfoPtr->moduleID         = FIM_MODULE_ID;
    VersionInfoPtr->sw_major_version = FIM_SW_MAJOR_VERSION;
    VersionInfoPtr->sw_minor_version = FIM_SW_MINOR_VERSION;
    VersionInfoPtr->sw_patch_version = FIM_SW_PATCH_VERSION;
  }

  DBG_FIM_GETVERSIONINFO_EXIT(VersionInfoPtr);
}
#endif /* FIM_VERSION_INFO_API == STD_ON */

/*------------------[FiM_Init]----------------------------------------------*/
FUNC(void, FIM_CODE) FiM_Init(
  P2CONST(FiM_ConfigType, AUTOMATIC, FIM_APPL_CONST) FiMConfigPtr)
{
  DBG_FIM_INIT_ENTRY(FiMConfigPtr);

  TS_PARAM_UNUSED(FiMConfigPtr);

#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON)
  /* initialize inhibition counters */
  FiM_DetermineInhibition();
#endif

#if (FIM_DEV_ERROR_DETECT == STD_ON)
  /* tag module as initialized */
  FiM_Initialized = TRUE;
#endif

  DBG_FIM_INIT_EXIT(FiMConfigPtr);
}

/*------------------[FiM_MainFunction]--------------------------------------*/
#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_OFF)
FUNC(void, FIM_CODE) FiM_MainFunction(void)
{
  DBG_FIM_MAINFUNCTION_ENTRY();

  /* Currently not supported */

  /* verify initialization-status before performing any actions */

  DBG_FIM_MAINFUNCTION_EXIT();
}
#endif

/*------------------[FiM_GetFunctionPermission]-----------------------------*/
FUNC(Std_ReturnType, FIM_CODE) FiM_GetFunctionPermission
(
  FiM_FunctionIdType                       FID,
  P2VAR(boolean, AUTOMATIC, FIM_APPL_DATA) Permission
)
{
  Std_ReturnType RetVal = E_NOT_OK;

  DBG_FIM_GETFUNCTIONPERMISSION_ENTRY(FID, Permission);

#if (FIM_DEV_ERROR_DETECT == STD_ON)
  if (NULL_PTR == Permission)
  {
    FIM_DET_REPORT_ERROR(
      FIM_SID_GET_FUNCTION_PERMISSION, FIM_E_INVALID_POINTER);
  }
  else if (FALSE == FiM_Initialized)
  {
    FIM_DET_REPORT_ERROR(
      FIM_SID_GET_FUNCTION_PERMISSION, FIM_E_WRONG_PERMISSION_REQ);
    *Permission = FALSE;
  }
  else if ((FID >= FIM_FID_NUM) || (0U == FID))
  {
    FIM_DET_REPORT_ERROR(
      FIM_SID_GET_FUNCTION_PERMISSION, FIM_E_FID_OUT_OF_RANGE);
    *Permission = FALSE;
  }
  else
#endif
  {
    /* Determine if the FID is inhibited */

#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_OFF)
    /* Get the number of events for this FID */
    const uint8 numEventCfg = FiM_FidConfig[FID].numEventCfg;
    /* Initially set the permission for the FID to run */
    boolean     perm        = TRUE;
    uint8_least ev;            /* Loop variable for event of FID */

    /* Loop through each assigned event */
    for (ev = 0U; (ev < numEventCfg) && (TRUE == perm); ++ev)
    {
      Dem_EventStatusExtendedType EventStatus;

      /* Get the current extended event status of the event */
      if (E_OK == Dem_GetEventStatus(
            FIM_EVENT_ID(FID, ev), &EventStatus))
      {
        const uint8 inhMaskIdx = FIM_INH_MASK_IDX(FID, ev);

        /* check if the Event Status matches the inihibition relation */
        if ((EventStatus & FiM_InhMask[inhMaskIdx])
            == FiM_InhResult[inhMaskIdx])
        {
          /* FID has no permission to run */
          perm = FALSE;
        }
      }
      else
      {
        /* FID has no permission to run */
        perm = FALSE;
      }
    }

    *Permission = perm;
#else /* FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON */
    uint16 fidInhibit;

    /* Enter the critical section */
    FIM_ENTER_EXCLUSIVE_AREA();

    fidInhibit = FiM_FidInhibitCounter[FID];

    /* Exit the critical section */
    FIM_EXIT_EXCLUSIVE_AREA();

    if (0U == fidInhibit)
    {
      /* FID has permission to run */
      *Permission = TRUE;
    }
    else
    {
      /* FID has no permission to run */
      *Permission = FALSE;
    }
#endif

    RetVal = E_OK;
  }

  DBG_FIM_GETFUNCTIONPERMISSION_EXIT(RetVal, FID, Permission);
  return RetVal;
}

/*------------------[FiM_DemTriggerOnEventStatus]---------------------------*/
#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON)
FUNC(void, FIM_CODE) FiM_DemTriggerOnEventStatus
(
  Dem_EventIdType EventId,
  uint8           EventStatusOld,
  uint8           EventStatusNew
)
{
  uint16 EvtIdx = 0U;

  DBG_FIM_DEMTRIGGERONEVENTSTATUS_ENTRY(
    EventId, EventStatusOld, EventStatusNew);

#if (FIM_DEV_ERROR_DETECT == STD_ON)
  if (FALSE == FiM_Initialized)
  {
    FIM_DET_REPORT_ERROR(
      FIM_SID_DEM_TRIGGER_ON_EVENT, FIM_E_WRONG_TRIGGER_ON_EVENT);
  }
  /* if the event Id is not existing, raise DET error */
  else if ((FIM_MAX_DEM_EVENT_ID < EventId) ||
           (FIM_EVENT_ID_INVALID == EventId))
  {
    FIM_DET_REPORT_ERROR(
       FIM_SID_DEM_TRIGGER_ON_EVENT, FIM_E_EVENTID_OUT_OF_RANGE);
  }
  else
#endif
  {
    /* invoke search algorithm to get the event-index */
    if (E_OK == FiM_EventSearch(EventId, &EvtIdx))
    {
      uint8_least fidIdx; /* loop variable for EventId related FIDs */
      uint8 numFids = FiM_EvtConfig[EvtIdx].numFids;

      /* loop through all FIDs for corresponding event */
      for (fidIdx = 0U; fidIdx < numFids; ++fidIdx)
      {
        const uint8 inhMaskIdx = FIM_INH_MASK_IDX(EvtIdx, fidIdx);
        FiM_FunctionIdType Fid = FIM_FID(EvtIdx, fidIdx);

        /* check if the required bits are changed */
        if ( (((uint8)(EventStatusOld ^ EventStatusNew)) & FiM_InhMask[inhMaskIdx]) != 0U )
        {
          /* check if the Event Status matches the inihibition relation */
          if (((EventStatusOld & FiM_InhMask[inhMaskIdx]) != FiM_InhResult[inhMaskIdx]) &&
               ((EventStatusNew & FiM_InhMask[inhMaskIdx]) == FiM_InhResult[inhMaskIdx]))
          {
            /* Enter the critical section */
            FIM_ENTER_EXCLUSIVE_AREA();

            FiM_FidInhibitCounter[Fid]++;

            /* Exit the critical section */
            FIM_EXIT_EXCLUSIVE_AREA();
          }
          else if (((EventStatusOld & FiM_InhMask[inhMaskIdx]) == FiM_InhResult[inhMaskIdx]) &&
                    ((EventStatusNew & FiM_InhMask[inhMaskIdx]) != FiM_InhResult[inhMaskIdx]) )
          {
            /* Enter the critical section */
            FIM_ENTER_EXCLUSIVE_AREA();

            if (0U != FiM_FidInhibitCounter[Fid])
            {
              FiM_FidInhibitCounter[Fid]--;
            }

            /* Exit the critical section */
            FIM_EXIT_EXCLUSIVE_AREA();
          }
          else
          {
            /* Dummy else to avoid Misra warning */
          }
        }
      }
    }
  }

  DBG_FIM_DEMTRIGGERONEVENTSTATUS_EXIT(
    EventId, EventStatusOld, EventStatusNew);
}
#endif /* FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON */

/*------------------[FiM_DemInit]-------------------------------------------*/
FUNC(void, FIM_CODE) FiM_DemInit(void)
{
  DBG_FIM_DEMINIT_ENTRY();

#if (FIM_DEV_ERROR_DETECT == STD_ON)
  if (FALSE == FiM_Initialized)
  {
    FIM_DET_REPORT_ERROR(FIM_SID_DEM_INIT, FIM_E_WRONG_TRIGGER_ON_EVENT);
  }
  else
#endif
  {
#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON)
    /* initialize inhibition counters */
    FiM_DetermineInhibition();
#endif
  }

  DBG_FIM_DEMINIT_EXIT();
}

/*==================[internal function definitions]=========================*/

#if (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON)

STATIC FUNC(void, FIM_CODE) FiM_DetermineInhibition(void)
{
  uint8 numFids;
  uint8_least EvIdx;

  DBG_FIM_DETERMINEINHIBITION_ENTRY();

  /* Enter the critical section */
  FIM_ENTER_EXCLUSIVE_AREA();

  /* clear all inhibition counter */
  TS_MemSet(FiM_FidInhibitCounter, 0U, (uint16)(sizeof(FiM_FidInhibitCounter)));

  /* Exit the critical section */
  FIM_EXIT_EXCLUSIVE_AREA();

  /* loop through all the events */
  for (EvIdx = 0U; EvIdx < FIM_EVENT_NUM; ++EvIdx)
  {
    uint8_least fidIdx; /* loop variable for EventId related FIDs */
    numFids = FiM_EvtConfig[EvIdx].numFids;

    /* loop through all FIDs for corresponding event */
    for (fidIdx = 0U; fidIdx < numFids; ++fidIdx)
    {
      FiM_FunctionIdType Fid = FIM_FID(EvIdx, fidIdx);
      Dem_EventStatusExtendedType EventStatus;

      /* get the current extended event status of the event */
      if (E_OK == Dem_GetEventStatus(FiM_EvtConfig[EvIdx].EventID, &EventStatus))
      {
        uint8 inhMaskIdx = FIM_INH_MASK_IDX(EvIdx, fidIdx);

        /* check if the event status matches the inihibition relation */
        if ((EventStatus & FiM_InhMask[inhMaskIdx]) == FiM_InhResult[inhMaskIdx])
        {
          /* Enter the critical section */
          FIM_ENTER_EXCLUSIVE_AREA();

          FiM_FidInhibitCounter[Fid]++;

          /* Exit the critical section */
          FIM_EXIT_EXCLUSIVE_AREA();
        }
      }
      /* else: E_NOT_OK can not be handled regarding FiM_FidInhibitCounter[]
               by the FiM itself (and should not returned by the Dem) */
    }
  }

  DBG_FIM_DETERMINEINHIBITION_EXIT();
}

STATIC FUNC(Std_ReturnType, FIM_CODE) FiM_EventSearch
(
  Dem_EventIdType                         EventId,
  P2VAR(uint16, AUTOMATIC, FIM_APPL_DATA) EvtIdx
)
{
  /* variable low, high, mid types are signed, because the variable high can get negative value for
   * the case when EventId is not configured to any FID and is smaller than the smallest EventId
   * configured in FiM */
  sint32_least low = 0;
  sint32_least high = (sint32_least)(FIM_EVENT_NUM - 1U);
  sint32_least mid = low;
  Std_ReturnType RetVal;

  DBG_FIM_EVENTSEARCH_ENTRY(EventId, EvtIdx);

  /* binary searching begins */
  while ((low <= high) && (EventId != FiM_EvtConfig[mid].EventID))
  {
    mid = (sint32_least)GET_MID_VALUE(high, low);

    if (EventId < FiM_EvtConfig[mid].EventID)
    {
      high = mid - 1;
    }
    else
    {
      low = mid + 1;
    }
  }

  if (EventId == FiM_EvtConfig[mid].EventID)
  {
    RetVal = E_OK;
    *EvtIdx = (uint16)mid;
  }
  else
  {
    RetVal = E_NOT_OK;
  }


  DBG_FIM_EVENTSEARCH_EXIT(RetVal, EventId, EvtIdx);
  return RetVal;
}

#endif /* (FIM_EVENT_UPDATE_TRIGGERED_BY_DEM == STD_ON) */

#define FIM_STOP_SEC_CODE
#include <MemMap.h>

/*==================[end of file]===========================================*/
